package com.kun.companion.core.ui.view;

import com.kun.companion.core.context.ContextService;
import com.kun.companion.core.exception.BizException;
import com.kun.companion.core.thread.ComThreadPool;
import com.kun.companion.core.ui.list.BaseListCell;
import com.kun.companion.core.ui.list.BaseListView;
import com.kun.companion.core.util.ComUtil;
import com.kun.companion.core.util.CssManager;
import javafx.geometry.Pos;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.*;

import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 自定义标签页容器，支持多位置布局和异步内容加载
 * <p>
 * 特性：
 * 1. 支持左/右标签栏位置
 * 2. 内容区域异步加载机制
 * 3. 自动尺寸适配父容器
 * 4. 标签页缓存功能
 * </p>
 *
 * @author gzc
 * @since 2025/2/16
 **/
public class KunTabPane extends BorderPane {
    public static final String CSS_PATH = "/com/kun/companion/css/kun-tab-pane.css";
    public static final String CSS_CLASS_NAME = "kun-tab-pane";
    /**
     * 区域尺寸比例常量
     */
    private static final BigDecimal CONTENT_WIDTH_RATIO = BigDecimal.valueOf(0.85D);
    private static final BigDecimal CONTENT_HEIGHT_RATIO = BigDecimal.valueOf(0.95D);
    private static final Location DEFAULT_TABS_LOCATION = Location.LEFT;

    /**
     * UI组件
     */
    private final BaseListView<KunTab> tabsView;
    private final StackPane contentPane;
    private final HBox logoBox;
    /**
     * 容器标题
     */
    private final Label contentTitleLabel;
    /**
     * 容器顶部视图
     */
    private final HBox contentTopBox;
    /**
     * 线程池
     */
    private final ComThreadPool comThreadPool;
    /**
     * 最后选择的标签ID
     */
    private volatile String lastSelectId = "";

    /**
     * 标签内容容器对象集合
     */
    protected final Map<String, Region> cacheMap = new ConcurrentHashMap<>(32);

    /**
     * 默认构造函数，标签栏位于左侧
     */
    public KunTabPane() {
        this(DEFAULT_TABS_LOCATION);
    }

    /**
     * 构造标签页容器
     *
     * @param tabsLocation 标签栏位置，支持LEFT/RIGHT/TOP/BOTTOM
     */
    public KunTabPane(Location tabsLocation) {
        this.tabsView = new TabListView();
        this.contentTitleLabel = new Label(" ");
        this.contentPane = createContentPane();
        this.logoBox = createLogoBox();
        this.contentTopBox = createContentTopBox();
        this.comThreadPool = ContextService.getBean(ComThreadPool.class);
        initializeBaseStyles();
        initializeComponents();
        setupLayout(tabsLocation);
        registerListeners();
    }

    /**
     * 创建菜单栏logo容器
     */
    private HBox createLogoBox() {
        HBox section = new HBox();
        section.getStyleClass().add("logo-box");
        Label logoTextLabel = new Label("AI坤坤伙伴");
        section.getChildren().add(logoTextLabel);
        return section;
    }

    protected HBox createContentTopBox() {
        HBox section = new HBox();
        section.getStyleClass().add("content-top-box");
        section.getChildren().add(this.contentTitleLabel);
        return section;
    }

    /**
     * 初始化基础样式
     */
    private void initializeBaseStyles() {
        getStyleClass().add(CSS_CLASS_NAME);
        getStylesheets().add(CssManager.getInstance().loadCss(CSS_PATH, true));
    }

    /**
     * 初始化核心组件
     */
    private void initializeComponents() {
        // 移除焦点边框样式
        CssManager.getInstance().disableFocusedBorderStyle(this.tabsView);
        // 创建滚动容器
        ScrollPane scrollPane = new ScrollPane(contentPane);
        CssManager.getInstance().disableFocusedBorderStyle(scrollPane);
        scrollPane.setFitToWidth(true);
        scrollPane.setFitToHeight(true);

        setCenter(scrollPane);
        setTop(new HBox(this.logoBox, this.contentTopBox));
    }

    /**
     * 创建内容区域
     */
    private StackPane createContentPane() {
        StackPane pane = new StackPane();
        pane.setAlignment(Pos.CENTER);
        return pane;
    }

    /**
     * 设置布局
     */
    private void setupLayout(Location tabsLocation) {
        switch (tabsLocation) {
            case LEFT -> setLeft(tabsView);
            case RIGHT -> setRight(tabsView);
            default -> throw new BizException("不支持的布局位置: " + tabsLocation);
        }

        // 垂直填充父容器
        VBox.setVgrow(this, Priority.ALWAYS);
    }

    /**
     * 注册尺寸和选择监听器
     */
    private void registerListeners() {
        // 尺寸变化监听
        widthProperty().addListener((obs, old, newVal) -> updateDimensions(newVal.doubleValue(), getHeight()));
        heightProperty().addListener((obs, old, newVal) -> updateDimensions(getWidth(), newVal.doubleValue()));

        // 标签选择监听
        tabsView.getSelectionModel().selectedItemProperty().addListener((obs, oldTab, newTab) -> {
            if (newTab == null) {
                return;
            }
            handleTabSelection(newTab);
        });
    }

    /**
     * 处理标签选择事件
     */
    private void handleTabSelection(KunTab newTab) {
        // 显示加载状态
        loading();
        lastSelectId = newTab.getId();
        // 异步加载容器内容
        comThreadPool.runAsync(() -> {
            Region cached = cacheMap.get(newTab.getId());
            Region content = newTab.getContentHandler().apply(cached);
            cacheMap.put(newTab.getId(), content);
            // 只显示最后点击的标签内容
            if (newTab.getId().equals(lastSelectId)) {
                ComUtil.uiThreadRun(() -> {
                    contentTitleLabel.setText(newTab.getCellText());
                    contentPane.getChildren().setAll(content);
                });
            }
        });
    }

    /**
     * 显示加载状态
     */
    private void loading() {
        ComUtil.uiThreadRun(() -> {
            VBox loadingBox = new VBox(new ProgressIndicator());
            loadingBox.setAlignment(Pos.CENTER);
            contentPane.getChildren().setAll(loadingBox);
        });
    }

    /**
     * 更新容器尺寸
     */
    private void updateDimensions(double width, double height) {
        // 更新菜单列表容器大小
        updateTabsSize(width, height);
        // 更新内容容器大小
        updateContentSize(width, height);
        // 更新顶部容器大小
        updateTitleSize(width, height);
    }

    /**
     * 更新内容区域尺寸
     */
    private void updateContentSize(double width, double height) {
        double updateWidth = BigDecimal.valueOf(width).multiply(CONTENT_WIDTH_RATIO).doubleValue() - 5;
        double updateHeight = BigDecimal.valueOf(height).multiply(CONTENT_HEIGHT_RATIO).doubleValue() - 5;
        contentPane.setPrefWidth(updateWidth);
        contentPane.setPrefHeight(updateHeight);
    }

    /**
     * 更新标签栏尺寸
     */
    private void updateTabsSize(double width, double height) {
        double updateWidth = BigDecimal.valueOf(width).multiply(BigDecimal.valueOf(1).subtract(CONTENT_WIDTH_RATIO)).doubleValue() - 5;
        double updateHeight = BigDecimal.valueOf(height).multiply(CONTENT_HEIGHT_RATIO).doubleValue() - 5;
        tabsView.setPrefWidth(updateWidth);
        tabsView.setPrefHeight(updateHeight);
    }

    /**
     * 更新标题栏尺寸
     */
    private void updateTitleSize(double width, double height) {
        double updateWidth1 = BigDecimal.valueOf(width).multiply(BigDecimal.valueOf(1).subtract(CONTENT_WIDTH_RATIO)).doubleValue() - 5;
        double updateWidth2 = BigDecimal.valueOf(width).multiply(CONTENT_WIDTH_RATIO).doubleValue() - 5;
        double updateHeight = BigDecimal.valueOf(height).multiply(BigDecimal.valueOf(1).subtract(CONTENT_HEIGHT_RATIO)).doubleValue() - 5;

        this.logoBox.setPrefWidth(updateWidth1);
        this.logoBox.setPrefHeight(updateHeight);
        this.contentTopBox.setPrefWidth(updateWidth2);
        this.contentTopBox.setPrefHeight(updateHeight);

    }

    public void addTab(KunTab kunTab) {
        tabsView.getItems().add(kunTab);
    }

    /**
     * 视图组件位置枚举
     */
    public enum Location {LEFT, RIGHT}

    /**
     * 自定义标签列表视图
     */
    private static class TabListView extends BaseListView<KunTab> {
        public TabListView() {
            super(lc -> new TabListCell());
        }
    }

    /**
     * 自定义标签列表单元格
     */
    private static class TabListCell extends BaseListCell<KunTab> {
        @Override
        protected void updateLayout() {
            // 仅显示图形内容
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }

        @Override
        protected void bindData(KunTab item) {
            // 显示标签文本
            setGraphic(new Label(item.getCellText()));
        }
    }
}
